package me.ingxin.android.activitylauncher

import android.os.Bundle
import android.util.Log
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment

/**
 * Created by ingxin on 2022/4/21
 */
internal class LaunchFragment<I, O> : Fragment() {

    private lateinit var callback: ActivityResultCallback<O>
    private lateinit var contract: ActivityResultContract<I, O>
    private var input: I? = null
    private var options: ActivityOptionsCompat? = null

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putInt(HOST_ACTIVITY_HASH_CODE, activity?.hashCode() ?: 0)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "LaunchFragment onCreate @${hashCode()}")
        if (this::contract.isInitialized && this::callback.isInitialized) {
            //A->B->C，在C中关闭B，直接回到A，callback也会触发（数据取决于是否调用setResult），不会泄漏fragment
            registerForActivityResult(contract) {
                callback.onActivityResult(it)
                removeSelf()
            }.launch(input, options)
        } else {
            //LaunchFragment跟随宿主Activity一起重建（可能是旋转，配置修改），应该让Activity去适配
            val lastHasCode = savedInstanceState?.getInt(HOST_ACTIVITY_HASH_CODE) ?: 0
            val hostName = activity?.javaClass?.simpleName
            Log.e(
                TAG,
                "$hostName@$lastHasCode is destroy, current activity is $hostName@${activity?.hashCode()}"
            )
            removeSelf()
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d(TAG, "LaunchFragment onDestroyView @${hashCode()}")
    }

    fun attach(
        input: I?,
        callback: ActivityResultCallback<O>,
        contract: ActivityResultContract<I, O>,
        options: ActivityOptionsCompat?
    ) {
        this.input = input
        this.contract = contract
        this.callback = callback
        this.options = options
    }

    private fun removeSelf() {
        parentFragmentManager.beginTransaction()
            .remove(this)
            .commitAllowingStateLoss()
    }

    companion object {
        private const val TAG = "ActivityLauncher"
        private const val HOST_ACTIVITY_HASH_CODE = "activity_hash_code"
    }

}